/*

 Authors: ZhangXuelian
 	
 
 Changes:
 	
	
*/

#include "coe_comm.h"

int on_receive_cmd(char * manufacturer_id, int product_id, char * device_serial_number, int task_no, char * json)
{
	//int handler = GetDeviceHandler(manufacturer_id,product_id,device_serial_number);
	//char * __json = str_assign(json);
	//add_task(MSG_ON_RECEIVE_CMD, handler, task_no, (int)__json, 0, 0, 0);
	return 1;
}

int on_receive_cmd_result(char * manufacturer_id, int product_id, char * device_serial_number, int task_no, int result)
{
	//int handler = GetDeviceHandler(manufacturer_id,product_id,device_serial_number);
	//add_task(MSG_ON_RECEIVE_CMD_RESULT, handler, task_no, result, 0, 0, 0);
	return 1;
}

// Notify
int on_receive_record(char * manufacturer_id, int product_id, char * device_serial_number, char * json)
{
	//int handler = GetDeviceHandler(manufacturer_id,product_id,device_serial_number);
	//char * __json = str_assign(json);
	//add_task(MSG_ON_RECEIVE_RECORD, handler, (int)__json, 0, 0, 0, 0);
	return 1; 
}

/**
 * 辅助函数：SDK的log输出回调
 * SDK内部调用改log输出函数，有助于开发者调试程序
 */
//#define SDK_DEBUG_INFO		1
//#define SDK_DEBUG_KEYINFO	2
//#define SDK_DEBUG_WARNING	3
//#define SDK_DEBUG_ERROR	    4
//#define SDK_DEBUG_LEVEL     SDK_DEBUG_INFO
void log_func(int level, const char* module, int line, const char* message)
{
	//if(level >= SDK_DEBUG_LEVEL)
	//{
	//	printf("module:%s - line[%d] - %s\n",module,line, message);
	//}
	add_task(MSG_ON_LOG_MESSAGE, level, (int)module, line, (int)message, 0, 0);
}

/**
* 登录完成的通知，errcode为0表示登录成功，其余请参考全局的错误码表
*/
void on_login_complete(int errcode)
{
	add_task(MSG_ON_LOGIN_COMPLETE, errcode, 0, 0, 0, 0, 0);
}

/**
* 在线状态变化通知， 状态（status）取值为 11 表示 在线， 取值为 21 表示  离线
* old是前一个状态，new是变化后的状态（当前）
*/
void on_online_status(int old, int new_status)
{
	add_task(MSG_ON_ONLINE_STATUS, old, new_status, 0, 0, 0, 0);
	return;
}

void on_receive_im_msg(int cmd, char* sender_imid, char* target_imid, char * pb_package, int pb_len)
{
	IMIDLEN *imidlen = (IMIDLEN *)malloc(sizeof(IMIDLEN));
	imidlen->sender_imid_len = strlen(sender_imid);
	imidlen->target_imid_len = strlen(target_imid);
	add_task(MSG_ON_RECEIVE_BASE_IM_NOTIFY, cmd, (int)sender_imid, (int)target_imid, (int)pb_package, pb_len, (int)imidlen);
	return;
}


void on_receive_mq_msg(int cmd, char * pb_package, int pb_len)
{
	add_task(MSG_ON_RECEIVE_BASE_MQ_NOTIFY, cmd, (int)pb_package, pb_len, 0, 0, 0);
	return;
}


void on_im_error_notify(int error_code)
{
	LOGE("%s: error_code = %d\n", __func__, error_code);
	add_task(MSG_ON_IM_ERROR_NOTIFY, error_code, 0, 0, 0, 0, 0);
	return;
}

void on_im_sdk_init_result_notify(int error_code)
{
	add_task(MSG_ON_IM_SDK_INIT_RESULT_NOTIFY, error_code, 0, 0, 0, 0, 0);
	return;
}

void handle_msg_on_online_status(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnOnlineStatusMethod, msg->param1, msg->param2);
	LOGE("%s: enter %d\n", __func__, 3);
}

void handle_msg_on_log_message(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	jstring _module,_message;
	_module = (*env)->NewStringUTF(env, (char *)msg->param2);
	_message = (*env)->NewStringUTF(env, (char *)msg->param4);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnLogFuncMethod, msg->param1,_module, msg->param3,_message);
	(*env)->DeleteLocalRef(env, _module);
	(*env)->DeleteLocalRef(env, _message);
	LOGE("%s: enter %d\n", __func__, 3);
}

void handle_msg_on_login_complete(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnLoginCompleteMethod, msg->param1);
	LOGE("%s: enter %d\n", __func__, 3);
}

void handle_msg_on_receive_cmd(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	jstring _json;
	_json = (*env)->NewStringUTF(env, (char *)msg->param3);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnReceiveCmdMethod, msg->param1, msg->param2,_json);
	(*env)->DeleteLocalRef(env, _json);
	LOGE("%s: enter %d\n", __func__, 3);
}

void handle_msg_on_receive_cmd_result(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnReceiveCmdResultMethod, msg->param1, msg->param2,msg->param3);
	LOGE("%s: enter %d\n", __func__, 3);
}

void handle_msg_on_receive_record(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;
	LOGE("%s: enter %d\n", __func__, 1);
	jstring _json;
	_json = (*env)->NewStringUTF(env, (char *)msg->param2);
	// 回调Java类的方法。
	(*env)->CallVoidMethod(env, c->sdk_listener, OnReceiveNotifyMethod, msg->param1,_json);
	(*env)->DeleteLocalRef(env, _json);
}

void handle_msg_on_receive_base_im_notify(JNIEnv* env, MSG * msg)
{
	COE_LIB * c = &g_coe_lib;

	IMIDLEN* plen = (IMIDLEN*)(msg->param6);

	//1. 得到sender imid
	jbyteArray simid_pb_package;
	simid_pb_package = (*env)->NewByteArray(env, plen->sender_imid_len);
	(*env)->SetByteArrayRegion(env, simid_pb_package, 0, plen->sender_imid_len, (jbyte*)(msg->param2));
	//2. 得到target imid
	jbyteArray timid_pb_package;
	timid_pb_package = (*env)->NewByteArray(env, plen->target_imid_len);
	(*env)->SetByteArrayRegion(env, timid_pb_package, 0, plen->target_imid_len, (jbyte*)(msg->param3));

	//3. 得到pb	data
	jbyteArray pb_package;
	pb_package = (*env)->NewByteArray(env, msg->param5);
	if (pb_package == NULL)
	{
		printf("[ERROR][JNI][%s] : pb is NULL !!!\n", __func__);
		return;
	}

	printf("[INFO][JNI][%s] : call back !!!\n", __func__);
	(*env)->SetByteArrayRegion(env, pb_package, 0, msg->param5, (jbyte*)(msg->param4));

	// 回调Java类的方法。
	int msgtype = msg->param1;
	switch (msgtype) {
	case MSGTYPE_GROUPCHAT:
	case MSGTYPE_GROUPCHAT_ACK:
		(*env)->CallVoidMethod(env, c->sdk_listener, OnBaseImProcessNotifyByGroupMethod, msg->param1, simid_pb_package, timid_pb_package, pb_package, msg->param5);
		break; 
	case MSGTYPE_PUBLICACC:
	case MSGTYPE_PUBLICACC_ACK:
		(*env)->CallVoidMethod(env, c->sdk_listener, OnBaseImProcessNotifyByPublicAccMethod, msg->param1, simid_pb_package, timid_pb_package, pb_package, msg->param5);
		break;
	case MSGTYPE_NOTICE:
	case MSGTYPE_NOTICE_ACK:
		(*env)->CallVoidMethod(env, c->sdk_listener, OnBaseImProcessNotifyByNoticeMethod, msg->param1, simid_pb_package, timid_pb_package, pb_package, msg->param5);
		break;
	case MSGTYPE_SYNC:
	case MSGTYPE_SYNC_ACK:
		(*env)->CallVoidMethod(env, c->sdk_listener, OnBaseImProcessNotifyBySyncMethod, msg->param1, simid_pb_package, timid_pb_package, pb_package, msg->param5);
		break;
	case MSGTYPE_CHAT:
	case MSGTYPE_CHAT_ACK:
	default:
		(*env)->CallVoidMethod(env, c->sdk_listener, OnBaseImProcessNotityMethod, msg->param1, simid_pb_package, timid_pb_package, pb_package, msg->param5);
		break;
	}

	(*env)->DeleteLocalRef(env, simid_pb_package);
	(*env)->DeleteLocalRef(env, timid_pb_package);
	(*env)->DeleteLocalRef(env, pb_package);

	// 释放数据
	if ((char*)(msg->param2))
	{
		free((char*)(msg->param2));
	}
	if ((char*)(msg->param3))
	{
		free((char*)(msg->param3));
	}
	if ((char*)(msg->param4))
	{
		free((char*)(msg->param4));
	}
	return;
}

/*
void handle_msg_on_im_error_notify(JNIEnv* env, MSG * msg)
{
	LOGI("[INFO][JNI][%s] : Enter 1018\n", __func__);
	COE_LIB * c = &g_coe_lib;

	LOGI("[INFO][JNI][%s] : msg code = %d\n", __func__, msg->param1);
	switch (msg->param1)
	{	
	case 100:
		c->is_net_ok = true;
		g_check_error_code = 100;
		break;
	case 101:	//网络异常, 例如连接了错误的wifi, 服务器未启动, 安卓手机没有打开wlan, 等等
		if (true == c->is_net_ok)
		{
            g_check_error_code = 101;		
		}
		break;
	case 102:
		//主动断开
        g_check_error_code = 102;
        break;
	case 103:
		//被迫下线
		g_check_error_code = 103;
		break;
    case 104:
		//JAVA未登陆CServer
        g_check_error_code = 104;
        break;
	default:
		break;
	}

	LOGI("[INFO][JNI][%s] : Exit\n", __func__);
}
*/

void handle_msg_on_im_error_notify(JNIEnv* env, MSG * msg)
{
	LOGI("[mdm][JNI][%s] : Enter 1129\n", __func__);
	COE_LIB * c = &g_coe_lib;

	LOGI("[mdm][JNI][%s] : msg code = %d\n", __func__, msg->param1);
	switch (msg->param1)
	{
	case 100:
		c->is_net_ok = true;
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 100);
		g_check_error_code = 0;
		break;
	case 101:	//网络异常, 例如连接了错误的wifi, 服务器未启动, 安卓手机没有打开wlan, 等等
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 101);
		c->is_net_ok = false;
		g_check_error_code = 0;
		break;
		g_check_error_code = 101;
	case 102:
		//主动断开
		g_check_error_code = 102;
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 102);
		g_check_error_code = 0;
		//   为了注销登录 //change by tan 2018.10.22 20:40 //
		g_flag_start_once = false;
		Java_com_COE_MdmSdkLib_API_deInitSdk(env, NULL);	//反初始化
		break;
	case 103:
		//被迫下线
		g_check_error_code = 103;
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 103);
		g_check_error_code = 0;
		//   为了强迫下线 //change by tan 2018.10.22 20:40 /
		g_flag_start_once = false;
		Java_com_COE_MdmSdkLib_API_deInitSdk(env, NULL);	//反初始化
		break;
	case 104:
		//JAVA未登陆CServer
		g_check_error_code = 104;
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 104);
		// 不停的发注册指令。

		g_check_error_code = 0;
		break;
	case 110:	//给安卓层的心跳回应
		(*env)->CallVoidMethod(env, c->sdk_listener, OnImErrorNotifyMethod, 110);
		break;
	default:
		break;
	}
	LOGI("[mdm][JNI][%s] : Exit\n", __func__);
}

void handle_msg_on_sdk_init_result_notify(JNIEnv* env, MSG * msg)
{
	LOGE("[mdm][JNI][%s] : Enter\n", __func__);
	COE_LIB * c = &g_coe_lib;
	(*env)->CallVoidMethod(env, c->sdk_listener, OnSdkInitResultNotifyMethod, msg->param1);

	switch (msg->param1)
	{
	case 0:				
		break;
	case -1:	//初始化失败		
		//Java_com_COE_MdmSdkLib_API_deInitSdk(env, NULL);	//反初始化
		//(*env)->DeleteGlobalRef(env, c->sdk_listener);
        g_check_error_code = 1;
		break;
	default:
		break;
	}

	LOGE("[mdm][JNI][%s] : Exit\n", __func__);
}

//
//----------------------------------------------------------------------------
// 不通过线程，直接由SDK中的线程调用。
//----------------------------------------------------------------------------
// 要求外边实现的，一个自动记录采集。给一个Json给内部。
// 记录上报的类型
//typedef enum __tag_coe_record_type
//{ 
//	COE_END_USER = 1 << 0,                      // 最终用户数据
//	COE_MANUFACTURER = 1 << 1,                  // 厂商数据
//	COE_BOTH = COE_END_USER | COE_MANUFACTURER, // 两者均是
//}COE_RECORD_TYPE;
// 库里直接同步回调这个函数。因此界面上不能做太多的运算。
// AUTO_SEND_RECORD_DATA 这一段内存在这个函数里开，会在库里释放，因此不要在这个函数里释放。
AUTO_SEND_RECORD_DATA * auto_send_record(char * manufacturer_id, int product_id, char * device_serial_number)
{
	//COE_LIB * c = &g_coe_lib;
	//AUTO_SEND_RECORD_DATA * data = malloc(sizeof(AUTO_SEND_RECORD_DATA));
	//memset(data,0,sizeof(AUTO_SEND_RECORD_DATA));
	//int handler = GetDeviceHandler(manufacturer_id,product_id,device_serial_number);
	//JNIEnv * env = NULL;
	//(*g_vm)->AttachCurrentThread(g_vm, &env, NULL);
	//jobject obj = (*env)->CallObjectMethod(env,c->sdk_listener,OnAutoSendRecordMethod,handler);
	//jstring jstr_json = (jstring)(*env)->GetObjectField(env,obj, g_cb_json_id);
	//
	//char * cstr = NULL;
	//cstr = Jstring2CStr(env,jstr_json);
	//if (cstr)
	//	 data->json = str_assign(cstr);
	//else
	//	data->json = str_assign("");
	//data->record_type = (*env)->GetIntField(env,obj, g_cb_record_type_id);
	//data->qos = (*env)->GetByteField(env, obj, g_cb_qos_id);
	//data->priority = (*env)->GetByteField(env, obj, g_cb_priority_id);
	//// 	根据device_serial_number的实际情况。去填充data
	////  我要报送的数据点，多个数据点组装成Json数组形式，控数分离，服务器不会解Json
	//// data->json = str_assign("我要报送的数据点，多个数据点组装成Json数组形式，控数分离，服务器不会解Json");
	//(*g_vm)->DetachCurrentThread(g_vm);
	//return data;
	//// 不要释放掉 data，以及Data里的成员，如果没有数据就初始化为NULL。
	return NULL;
}

// 要求Java应用层实现的，一个自动状态发送。给一个Json给内部。
char * auto_send_status() 
{
	//COE_LIB * c = &g_coe_lib;
	//JNIEnv* env = NULL;
	//(*g_vm)->AttachCurrentThread(g_vm, &env, NULL);
	//jstring jstr = (jstring)(*env)->CallObjectMethod(env, c->sdk_listener,OnAutoSendStatusMethod);
	//char * cstr = NULL;
	////cstr = Jstring2CStr(env,jstr);
	//// convert the Java String to use it in C
	//cstr = (*env)->GetStringUTFChars(env,jstr, 0);
	//printf("%s" , cstr);
	//char * __cstr = NULL;
	//if (cstr)
	//	__cstr = str_assign(__cstr);
	//(*env)->ReleaseStringUTFChars(env,jstr, cstr);  
	//(*g_vm)->DetachCurrentThread(g_vm);
	//return cstr;
	return NULL;
}
